﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PJ.Business.SalePurchase;
using System.Windows;
using PJ.Business;
using PJ.Business.Inventory;
using Microsoft.Practices.Composite.Events;
using PJ.Data;

namespace PJ.Presentation.SalePurchase
{
    public abstract class ShoppingCartItemModel : BusinessObjectViewModel, IShoppingCartItemModel
    {
        #region Constructor
        protected ShoppingCartItemModel(IView view, IEventAggregator aggregator, IShoppingCartItemService service)
            : base(view, aggregator, service)
        {
        }

        protected ShoppingCartItemModel(string globalId, IShoppingCartItemService service)
            : base(globalId, service)
        {
        }

        protected ShoppingCartItemModel(IBusinessObject obj, IShoppingCartItemService service)
            : base(obj, service)
        {
        }

        protected ShoppingCartItemModel()
        {
        }

        #endregion

        #region Inteface implementation

        /// <summary>
        /// GetValues. Sets the businness object properties using the model property values
        /// </summary>
        /// <param name="businessObject">business object to update</param>
        public override IBusinessObject GetValues()
        {
            if (base.GetValues() == null)
            {
                if (IsStringNull(OwnerId) && IsStringNull(InventoryItemId) && IsStringNull(UnitId) &&
                    Order == 0 && Quantity == 0)
                    return null;
            }
            BusinessObject.OwnerId = OwnerId;
            BusinessObject.Order = Order;
            BusinessObject.InventoryItemId = InventoryItemId;
            BusinessObject.Quantity = Quantity;
            BusinessObject.UnitId = UnitId;
            return BusinessObject;
        }
        /// <summary>
        /// SetValues. Sets the model properties using the businessobject property values
        /// </summary>
        /// <param name="businessObject"></param>
        public override void SetValues(IBusinessObject businessObject, bool saveBefore)
        {
            base.SetValues(businessObject, saveBefore);
            if (businessObject == null)
            {
                OwnerId = null;
                Order = 0L;
                InventoryItemId = null;
                Quantity = 0L;
                UnitId = null;
            }
            else
            {
                OwnerId = BusinessObject.OwnerId;
                Order = BusinessObject.Order;
                InventoryItemId = BusinessObject.InventoryItemId;
                Quantity = BusinessObject.Quantity;
                UnitId = BusinessObject.UnitId;
            }
        }


        public string InventoryItemId
        {
            get { return (string)ThreadUnsafeGetValue(InventoryItemIdProperty); }
            set { ThreadUnsafeSetValue(InventoryItemIdProperty, value); }
        }

        public double Quantity
        {
            get { return (double)ThreadUnsafeGetValue(QuantityProperty); }
            set { ThreadUnsafeSetValue(QuantityProperty, value); }
        }

        public string UnitId
        {
            get { return (string)ThreadUnsafeGetValue(UnitIdProperty); }
            set { ThreadUnsafeSetValue(UnitIdProperty, value); }
        }

        public string OwnerId
        {
            get { return (string)ThreadUnsafeGetValue(OwnerIdProperty); }
            set 
            {
                ThreadUnsafeSetValue(OwnerIdProperty, value); 
            }
        }

        public double Order
        {
            get { return (double)ThreadUnsafeGetValue(OrderProperty); }
            set { ThreadUnsafeSetValue(OrderProperty, value); }
        }

        #endregion

        #region Inteface override

        public new IShoppingCartItemService Service
        {
            get
            {
                return (IShoppingCartItemService)base.Service;
            }
        }

        #endregion

        #region Public

        public static readonly DependencyProperty OwnerIdProperty =
            DependencyProperty.Register("OwnerId", typeof(string), typeof(ShoppingCartModel), new UIPropertyMetadata(""));


        public static readonly DependencyProperty InventoryItemIdProperty =
            DependencyProperty.Register("InventoryItemId", typeof(string), typeof(ShoppingCartItemModel),
                new PropertyMetadata("",
                    new PropertyChangedCallback(OnInventoryItemIdChanged),
                    new CoerceValueCallback(OnInventoryItemIdCoerce)));

        public static readonly DependencyProperty InventoryItemProperty =
           DependencyProperty.Register("InventoryItem", typeof(IInventoryItem), typeof(ShoppingCartItemModel));

        public static readonly DependencyProperty QuantityProperty =
            DependencyProperty.Register("Quantity", typeof(double), typeof(ShoppingCartItemModel));

        public static readonly DependencyProperty OrderProperty =
            DependencyProperty.Register("Order", typeof(double), typeof(ShoppingCartItemModel));

        public static readonly DependencyProperty UnitIdProperty =
            DependencyProperty.Register("UnitId", typeof(string), typeof(ShoppingCartItemModel));

        public IInventoryItem InventoryItem
        {
            get { return (IInventoryItem)ThreadUnsafeGetValue(InventoryItemProperty); }
            set { ThreadUnsafeSetValue(InventoryItemProperty, value); }
        }

        #endregion

        #region Protected

        protected abstract IInventoryItemOrderParamService InventoryItemOrderParamService { get; }

        protected override bool ValuesChanged()
        {
            if (base.ValuesChanged())
                return true;
            else
            {
                if (IsBusinessObjectNull)
                {
                    if (IsStringNull(OwnerId) && IsStringNull(InventoryItemId) && IsStringNull(UnitId) &&
                        Order == 0 && Quantity == 0)
                        return false;
                }
                if (StringEqual(InventoryItemId, BusinessObject.InventoryItemId) && StringEqual(UnitId, BusinessObject.UnitId)
                    && StringEqual(OwnerId, BusinessObject.OwnerId) && Order == BusinessObject.Order && Quantity == BusinessObject.Quantity)
                    return false;
                else
                    return true;
            }
        }

        protected new IShoppingCartItem BusinessObject { get { return base.BusinessObject as IShoppingCartItem; } }

        #endregion

        #region Private

        private static void OnInventoryItemIdChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ShoppingCartItemModel model = (ShoppingCartItemModel)d;
            try
            {
                if (model._InventItemIdChange)
                    return;
                model._InventItemIdChange = true;
                if (d == null)
                    throw new ArgumentNullException("d");
                string itemId;
                double quantity;
                string unitId;
                if (model.Service.DecodeExpression((string)e.NewValue, out itemId, out quantity, out unitId))
                {
                    if (model.Quantity == 0)
                    {
                        model.Quantity = quantity;
                        model.UnitId = unitId;
                    }
                    if (model.UnitId == null || model.UnitId == "")
                        model.UnitId = unitId;
                    model.InventoryItem = (IInventoryItem)model.Service.InventoryItemService.GetById(itemId, GetDataMode.UseCache);
                    model.InventoryItemId = itemId;
                }
                else
                {
                    model.Quantity = 0;
                    model.UnitId = null;
                    model.InventoryItemId = null;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "\n" + ex.StackTrace);
            }
            finally
            {
                model._InventItemIdChange = false;
            }
        }
        private static object OnInventoryItemIdCoerce(DependencyObject d, object val)
        {
            return val;
        }

        #endregion

        #region Field

        private string _Initial_InventoryItemId;
        private string _Initial_UnitId;
        private double _Initial_Quantity;

        private bool _InventItemIdChange;
        #endregion



    }
}
